Streams এবং Buffers (স্ট্রিম এবং বাফার)

Computer Programming - নোড জেএস (Node.js)
187

Streams এবং Buffers হল Node.js এর দুটি গুরুত্বপূর্ণ কনসেপ্ট, যা বিশেষভাবে বড় ডেটা সেট এবং ডেটা ট্রান্সফারের জন্য ব্যবহৃত হয়। এগুলি অ্যাসিনক্রোনাস এবং কার্যকরীভাবে ডেটা প্রক্রিয়াকরণের সুবিধা দেয়। এখানে আমরা স্ট্রিম এবং বাফার সম্পর্কে বিস্তারিত আলোচনা করব এবং Node.js এ এগুলির ব্যবহার দেখব।


১. Streams (স্ট্রিম)

স্ট্রিম একটি ডেটা ট্রান্সফারের উপায়, যেখানে ডেটা একে একে পাঠানো বা গ্রহণ করা হয়, পুরো ডেটাটি একসাথে মেমরিতে লোড না করে। এটি খুবই উপকারী যখন আপনি বড় আকারের ডেটা (যেমন ফাইল, ভিডিও, অথবা নেটওয়ার্ক রিকোয়েস্ট) প্রক্রিয়া করছেন।

Node.js-এ চার ধরনের স্ট্রিম আছে:

  1. Readable streams: যেগুলি ডেটা রিড করতে ব্যবহৃত হয়।
  2. Writable streams: যেগুলি ডেটা লিখতে ব্যবহৃত হয়।
  3. Duplex streams: যেগুলি ডেটা পড়তে এবং লিখতে ব্যবহৃত হয়।
  4. Transform streams: যেগুলি ডেটা ট্রান্সফর্ম করতে ব্যবহৃত হয়।

স্ট্রিম ব্যবহার:

Node.js স্ট্রিমের সাহায্যে আপনি বড় আকারের ডেটা অ্যাসিনক্রোনাসভাবে প্রক্রিয়া করতে পারবেন, যা মেমরি ব্যবস্থাপনাকে উন্নত করে এবং অ্যাপ্লিকেশনের পারফরম্যান্স বাড়ায়।

Readable Stream:
const fs = require('fs');

// Readable Stream ব্যবহার
const readStream = fs.createReadStream('example.txt', 'utf8');

readStream.on('data', (chunk) => {
  console.log('Reading chunk:', chunk);  // প্রতিটি chunk ডেটা রিড করার পর
});

readStream.on('end', () => {
  console.log('Reading completed.');
});

এখানে fs.createReadStream() ফাংশনটি একটি Readable Stream তৈরি করে, যা ফাইল থেকে ডেটা একে একে পড়বে।

Writable Stream:
const fs = require('fs');

// Writable Stream ব্যবহার
const writeStream = fs.createWriteStream('output.txt');

writeStream.write('Hello, Node.js!\n');  // ডেটা লেখা
writeStream.write('This is a writable stream example.\n');
writeStream.end();  // লেখার শেষ

এখানে fs.createWriteStream() ফাংশনটি একটি Writable Stream তৈরি করে, যা ফাইলে ডেটা লিখে।

Duplex Stream:
const { Duplex } = require('stream');

// Duplex Stream তৈরি
const duplexStream = new Duplex({
  read(size) {
    this.push('Hello, World!');  // পাঠানোর ডেটা
    this.push(null);  // ডেটা শেষ
  },
  write(chunk, encoding, callback) {
    console.log('Writing chunk:', chunk.toString());  // প্রাপ্ত ডেটা
    callback();
  }
});

duplexStream.on('data', (chunk) => {
  console.log('Received chunk:', chunk.toString());
});

duplexStream.write('Test data\n');

এখানে Duplex স্ট্রিমটি ডেটা পাঠাতে এবং গ্রহণ করতে সক্ষম।


২. Buffers (বাফার)

Buffer হল একটি ব্লক ডেটা স্টোরেজ, যা বাইনারি ডেটা (যেমন ফাইল বা নেটওয়ার্ক ডেটা) সংরক্ষণ করতে ব্যবহৃত হয়। JavaScript এর সাধারণ স্ট্রিং টাইপ শুধুমাত্র ইউনিকোড ক্যারেক্টারস (UTF-8) সমর্থন করে, কিন্তু Buffer টাইপ বাইনারি ডেটা (যেমন, ছবি, অডিও, ভিডিও) সাপোর্ট করে।

Node.js এ Buffer ক্লাস ব্যবহার করা হয় বাইনারি ডেটা পরিচালনা করার জন্য।

Buffer তৈরি:

const buf = Buffer.from('Hello, Node.js!', 'utf8');  // একটি নতুন বাফার তৈরি
console.log(buf);  // <Buffer 48 65 6c 6c 6f 2c 20 4e 6f 64 65 2e 6a 73 21>

এখানে Buffer.from() মেথড ব্যবহার করে স্ট্রিং 'Hello, Node.js!' থেকে একটি বাফার তৈরি করা হয়েছে। বাফারের মধ্যে বাইনারি ডেটা সঞ্চিত থাকে।

Buffer এর দৈর্ঘ্য:

const buf = Buffer.from('Hello');
console.log(buf.length);  // 5 (ডেটার দৈর্ঘ্য)

এখানে buf.length ব্যবহার করে বাফারের দৈর্ঘ্য বের করা হয়েছে।

Buffer এর সেলাই (Concatenation):

const buf1 = Buffer.from('Hello');
const buf2 = Buffer.from('World');
const combined = Buffer.concat([buf1, buf2]);

console.log(combined.toString());  // "HelloWorld"

এখানে Buffer.concat() ব্যবহার করে দুটি বাফার একত্রিত করা হয়েছে এবং তারপরে toString() মেথড দিয়ে তা স্ট্রিং এ রূপান্তরিত করা হয়েছে।

Buffer এর অংশ (Slicing):

const buf = Buffer.from('Hello, Node.js!');
const sliced = buf.slice(7, 11);
console.log(sliced.toString());  // "Node"

এখানে slice() মেথড ব্যবহার করে বাফারের একটি অংশ কাটা হয়েছে।


৩. স্ট্রিম এবং বাফার সম্পর্ক

স্ট্রিম এবং বাফার একে অপরের সাথে সম্পর্কিত। যখন আপনি একটি বড় ফাইল বা ডেটা স্ট্রিমের মাধ্যমে পাঠান, তখন স্ট্রিমের chunk গুলো সাধারণত Buffer আকারে আসে। স্ট্রিমের সাহায্যে আপনি এই Buffer গুলো একে একে প্রক্রিয়া করতে পারেন, যা মেমরির দক্ষ ব্যবহারে সহায়তা করে।

উদাহরণ (স্ট্রিম এবং বাফার একত্রিত করা):

const fs = require('fs');
const readStream = fs.createReadStream('largeFile.txt');
const writeStream = fs.createWriteStream('output.txt');

readStream.on('data', (chunk) => {
  console.log('Received chunk:', chunk);
  writeStream.write(chunk);  // বাফার লেখা হচ্ছে
});

readStream.on('end', () => {
  console.log('File reading completed');
  writeStream.end();
});

এখানে একটি বড় ফাইল থেকে ডেটা স্ট্রিম করা হচ্ছে এবং প্রতিটি chunk একটি Buffer হিসেবে আসে, যা আমরা Writable Stream এ লেখার জন্য ব্যবহার করছি।


সারাংশ

স্ট্রিম এবং বাফার হল Node.js এর দুটি অত্যন্ত গুরুত্বপূর্ণ কনসেপ্ট, যেগুলি বড় আকারের ডেটা প্রক্রিয়াকরণে ব্যবহৃত হয়। স্ট্রিম অ্যাসিনক্রোনাসভাবে ডেটা প্রবাহিত করার উপায় প্রদান করে এবং বাফার বাইনারি ডেটা সংরক্ষণ করার উপযোগী। এই দুটি কনসেপ্টের সাহায্যে আপনি মেমরি ব্যবস্থাপনা উন্নত করতে পারেন এবং দ্রুত পারফরম্যান্স নিশ্চিত করতে পারেন, বিশেষ করে যখন আপনি বড় ফাইল বা ডেটা নিয়ে কাজ করছেন।

Content added By

Streams এর ধারণা এবং প্রয়োজনীয়তা

339

Streams হল একটি গুরুত্বপূর্ণ কনসেপ্ট, যা Node.js এর I/O (Input/Output) অপারেশনকে আরও কার্যকরী এবং স্কেলেবল করে তোলে। এটি ডেটা প্রক্রিয়াকরণের একটি ধারাবাহিক পদ্ধতি, যেখানে আপনি একটি বড় ডেটা সেট (যেমন ফাইল, নেটওয়ার্ক ডেটা) একসাথে না নিয়ে আসলে, ডেটার উপর বিভিন্ন অপারেশন করে যেতে পারেন। Node.js এ, Streams বিশেষ করে বড় আকারের ডেটা বা রিয়েল-টাইম ডাটা প্রক্রিয়াকরণের জন্য ব্যবহৃত হয়।

Streams এর মাধ্যমে আপনি ডেটাকে পিসে পিসে প্রসেস করতে পারেন, যার ফলে পুরো ডেটা একসাথে মেমোরিতে না রেখে, কম মেমোরি ব্যবহার করে দ্রুত কাজ করতে পারেন।


১. Streams এর মৌলিক ধারণা

Streams হলো data flow এর একটি ধরনের অবজেক্ট, যা নির্দিষ্ট আকারের ডেটা তৈরি বা গ্রহণ করে। Streams সাধারণত চার ধরনের হয়:

  1. Readable Streams: এই ধরনের স্ট্রিম থেকে ডেটা পড়া যায়। উদাহরণ: ফাইল থেকে ডেটা পড়া, HTTP রিকোয়েস্ট থেকে ডেটা গ্রহণ।
  2. Writable Streams: এই ধরনের স্ট্রিমে ডেটা লেখা যায়। উদাহরণ: ফাইলে ডেটা লেখা, HTTP রেসপন্সে ডেটা পাঠানো।
  3. Duplex Streams: এই ধরনের স্ট্রিমে ডেটা উভয় দিকে (পড়া এবং লেখা) প্রবাহিত হয়। উদাহরণ: TCP sockets।
  4. Transform Streams: এটি একটি বিশেষ ধরনের Duplex stream, যেখানে ডেটা প্রক্রিয়া করার সময় লেখা ও পড়ার মধ্যে পরিবর্তন করা হয়। উদাহরণ: এনক্রিপশন বা কম্প্রেশন।

২. Streams এর প্রয়োজনীয়তা

Streams ব্যবহারের মাধ্যমে কিছু বিশেষ সুবিধা পাওয়া যায়, যা বড় আকারের অ্যাপ্লিকেশন বা ডেটা ইন্টারঅ্যাকশনকে আরও কার্যকরী করে:

a. কম মেমোরি ব্যবহারের সুবিধা:

  • একসাথে সব ডেটা মেমোরিতে না রেখে, আপনি পিসে পিসে ডেটা প্রক্রিয়া করতে পারেন। ফলে সিস্টেমের মেমোরি ব্যবহারের চাপ কমে যায়।
  • উদাহরণ: যদি একটি বড় ফাইল পড়া হয়, তখন স্ট্রিম ব্যবহার করলে পুরো ফাইল একসাথে মেমোরিতে লোড না হয়ে, পিসে পিসে লোড হবে।

b. রিয়েল-টাইম ডেটা প্রক্রিয়াকরণ:

  • Streams দিয়ে আপনি ডেটা একযোগভাবে প্রবাহিত করতে পারেন, যেমন রিয়েল-টাইম ফাইল আপলোড বা ডাউনলোড, ভিডিও স্ট্রিমিং, ইত্যাদি। এর মাধ্যমে ডেটা প্রক্রিয়া হওয়ার সাথে সাথে তা পাঠানো সম্ভব হয়।

c. দ্রুত পারফরম্যান্স:

  • স্ট্রিম ব্যবহার করে, ডেটা প্রক্রিয়াকরণ দ্রুত হয় কারণ আপনি এক সময়ের মধ্যে একাধিক ডেটা অপারেশন করতে পারেন। যেমন, আপনি ডেটা পড়তে পড়তে তা ট্রান্সফর্ম করতে বা প্রেরণ করতে পারেন।

d. অ্যাসিনক্রোনাস অপারেশন:

  • Streams অ্যাসিনক্রোনাস অপারেশন সরবরাহ করে, যার মানে হল যে আপনার কোড ব্লক হয় না এবং অন্য কাজগুলি চলতে থাকে, যতক্ষণ না স্ট্রিম অপারেশন সম্পন্ন হয়।

৩. Streams এর উদাহরণ

a. Readable Stream (ফাইল পড়ার উদাহরণ)

Node.js এ fs.createReadStream() ফাংশন ব্যবহার করে আপনি ফাইল থেকে ডেটা পড়ে স্ট্রিম করতে পারেন।

const fs = require('fs');

// ফাইল থেকে ডেটা পড়া
const readableStream = fs.createReadStream('largefile.txt', 'utf8');

// স্ট্রিমে ডেটা পড়ার সময়, ডেটা লগ করা
readableStream.on('data', (chunk) => {
  console.log('Reading data chunk:', chunk);
});

// স্ট্রিম শেষ হলে
readableStream.on('end', () => {
  console.log('File read complete.');
});

এখানে, ফাইলটি একবারে পুরোপুরি না পড়ে, স্ট্রিমের মাধ্যমে ডেটা পিসে পিসে পড়া হচ্ছে।

b. Writable Stream (ফাইলে ডেটা লেখা)

const fs = require('fs');

// ফাইলে ডেটা লেখা
const writableStream = fs.createWriteStream('output.txt');

// ডেটা লেখার সময়
writableStream.write('Hello, this is some data!\n');
writableStream.write('Another line of text!\n');

// লেখার পর স্ট্রিম বন্ধ করা
writableStream.end(() => {
  console.log('Writing complete.');
});

এখানে, ডেটা ফাইলে স্ট্রিমের মাধ্যমে লেখা হচ্ছে এবং শেষে স্ট্রিমটি বন্ধ করা হচ্ছে।

c. Duplex Stream (টিসিপি সোকেট)

const net = require('net');

// টিসিপি সোকেট তৈরি করা
const server = net.createServer((socket) => {
  socket.write('Hello, client!\n');
  socket.on('data', (data) => {
    console.log('Received from client:', data.toString());
  });
});

server.listen(8080, () => {
  console.log('Server is listening on port 8080');
});

এখানে, net.createServer() একটি duplex স্ট্রিম তৈরি করছে যেখানে একে অপরের সাথে ডেটা পাঠানো এবং গ্রহণ করা যাচ্ছে।


৪. Transform Stream (ডেটা ট্রান্সফর্ম)

const { Transform } = require('stream');

// একটি ট্রান্সফর্ম স্ট্রিম তৈরি করা
const transformStream = new Transform({
  transform(chunk, encoding, callback) {
    // ডেটার পেছনে কিছু পরিবর্তন করা
    this.push(chunk.toString().toUpperCase()); // টেক্সটকে uppercase করা
    callback();
  }
});

// ইনপুট স্ট্রিমের মাধ্যমে ডেটা পাঠানো
process.stdin.pipe(transformStream).pipe(process.stdout);

এখানে, একটি transform stream তৈরি করা হয়েছে, যেখানে ইনপুট ডেটা কনভার্ট করা হচ্ছে এবং তারপর আউটপুট হিসেবে পাঠানো হচ্ছে।


সারাংশ

Streams হল Node.js এর একটি গুরুত্বপূর্ণ কনসেপ্ট যা অ্যাসিনক্রোনাস এবং non-blocking ডেটা প্রক্রিয়াকরণের জন্য ব্যবহৃত হয়। Streams ব্যবহার করে আপনি কম মেমোরি ব্যবহার করে বড় আকারের ডেটা প্রক্রিয়া করতে পারেন এবং রিয়েল-টাইম অ্যাপ্লিকেশন তৈরি করতে পারেন। Readable, Writable, Duplex, এবং Transform স্ট্রিমগুলি Node.js এর I/O অপারেশন আরও দক্ষ এবং দ্রুত করতে সাহায্য করে।

Content added By

Readable এবং Writable Streams তৈরি করা

176

Streams হলো Node.js এর একটি শক্তিশালী বৈশিষ্ট্য যা ডেটা পড়া বা লেখা করার জন্য ব্যবহৃত হয়। স্ট্রিমের মাধ্যমে আপনি ডেটাকে টুকরো টুকরো করে প্রসেস করতে পারেন, ফলে এটি বড় ডেটা বা ফাইল হ্যান্ডলিংয়ে কার্যকরী হয়ে ওঠে। Node.js এ দুটি প্রধান ধরনের স্ট্রিম রয়েছে: Readable Streams এবং Writable Streams


১. Readable Streams

Readable Stream এমন একটি স্ট্রিম যা ডেটা "পড়ে" (read) নেয়। এটি একটি সঞ্চিত ডেটা স্ট্রিম করে, যা ডেটা ইভেন্টের মাধ্যমে প্রসেস করা হয়। যেমন, ফাইল থেকে ডেটা পড়া বা HTTP রিকোয়েস্ট থেকে ডেটা গ্রহণ করা।

Readable Stream তৈরি করা

Node.js এর Readable ক্লাস থেকে একটি কাস্টম Readable Stream তৈরি করা যেতে পারে। নিচে একটি উদাহরণ দেওয়া হল, যেখানে একটি কাস্টম Readable Stream তৈরি করা হচ্ছে:

const { Readable } = require('stream');

// একটি কাস্টম Readable Stream তৈরি করা
class MyReadableStream extends Readable {
  constructor(options) {
    super(options);
    this.data = ['Hello', ' ', 'World', '!', '\n']; // আমাদের ডেটা
    this.index = 0;
  }

  // _read() মেথড: স্ট্রিমের ডেটা পাঠানোর জন্য ব্যবহৃত হয়
  _read(size) {
    if (this.index < this.data.length) {
      // ডেটা পাঠানো
      this.push(this.data[this.index]);
      this.index++;
    } else {
      // ডেটা শেষ, স্ট্রিম বন্ধ
      this.push(null);
    }
  }
}

// কাস্টম Readable Stream ব্যবহার করা
const myStream = new MyReadableStream();

myStream.on('data', (chunk) => {
  console.log('Received chunk:', chunk.toString());
});

myStream.on('end', () => {
  console.log('No more data.');
});

Output:

Received chunk: Hello
Received chunk:  
Received chunk: World
Received chunk: !
Received chunk: 
No more data.

এখানে, _read() মেথডটি কাস্টম Readable স্ট্রিম তৈরি করার জন্য ব্যবহৃত হয়েছে। এই মেথডে ডেটা push করা হয় এবং শেষ হলে null পাঠিয়ে স্ট্রিম বন্ধ করা হয়।


২. Writable Streams

Writable Stream এমন একটি স্ট্রিম যা ডেটা "লেখে" (write) নেয়। এটি ডেটা গ্রহণ করে এবং সেই ডেটা নির্দিষ্ট জায়গায় (যেমন ফাইল, নেটওয়ার্ক, ইত্যাদি) লেখে।

Writable Stream তৈরি করা

Node.js এর Writable ক্লাস থেকে একটি কাস্টম Writable Stream তৈরি করা যেতে পারে। নিচে একটি উদাহরণ দেওয়া হলো:

const { Writable } = require('stream');

// একটি কাস্টম Writable Stream তৈরি করা
class MyWritableStream extends Writable {
  constructor(options) {
    super(options);
  }

  // _write() মেথড: স্ট্রিমের ডেটা লেখার জন্য ব্যবহৃত হয়
  _write(chunk, encoding, callback) {
    console.log('Writing chunk:', chunk.toString());
    callback(); // ডেটা লেখার পর কলব্যাক কল করা
  }
}

// কাস্টম Writable Stream ব্যবহার করা
const myStream = new MyWritableStream();

myStream.write('Hello, ');
myStream.write('World!');
myStream.end();  // স্ট্রিম বন্ধ

Output:

Writing chunk: Hello, 
Writing chunk: World!

এখানে, _write() মেথডটি ডেটা লেখার জন্য ব্যবহৃত হয়েছে। chunk আর্গুমেন্টে ডেটা পাস করা হয়, এবং callback() কল করে লেখার কাজ সম্পন্ন করা হয়।


৩. Readable এবং Writable Streams একসাথে ব্যবহার করা

Readable এবং Writable Streams একসাথে ব্যবহার করে আপনি একটি স্ট্রিমের ডেটা অন্য স্ট্রিমে পাঠাতে পারেন। এটি স্ট্রিম পাইপলাইন তৈরি করার জন্য ব্যবহৃত হয়।

উদাহরণ: Readable এবং Writable Stream এর মধ্যে ডেটা পিপ করা

const { Readable, Writable } = require('stream');

// Readable Stream তৈরি করা
class MyReadableStream extends Readable {
  constructor(options) {
    super(options);
    this.data = ['Hello', ' ', 'World', '!\n'];
    this.index = 0;
  }

  _read(size) {
    if (this.index < this.data.length) {
      this.push(this.data[this.index]);
      this.index++;
    } else {
      this.push(null);
    }
  }
}

// Writable Stream তৈরি করা
class MyWritableStream extends Writable {
  constructor(options) {
    super(options);
  }

  _write(chunk, encoding, callback) {
    console.log('Received:', chunk.toString());
    callback();
  }
}

// Readable Stream থেকে Writable Stream এ ডেটা পিপ করা
const readableStream = new MyReadableStream();
const writableStream = new MyWritableStream();

// পিপিং করা
readableStream.pipe(writableStream);

Output:

Received: Hello
Received:  
Received: World
Received: !

এখানে, pipe() মেথড ব্যবহার করা হয়েছে, যা Readable Stream থেকে ডেটা গ্রহণ করে তা Writable Stream এ পাঠায়। স্ট্রিমের মধ্যে ডেটা প্রবাহিত হওয়ার সময়, Received: বার্তা সহ ডেটা প্রিন্ট করা হচ্ছে।


সারাংশ

  • Readable Streams: ডেটা পড়ার জন্য ব্যবহৃত হয়, যেখানে ডেটা টুকরো টুকরো করে পাঠানো হয় এবং _read() মেথডের মাধ্যমে পাঠানো হয়।
  • Writable Streams: ডেটা লেখার জন্য ব্যবহৃত হয়, যেখানে ডেটা _write() মেথডের মাধ্যমে লেখা হয়।
  • Streams Node.js-এ বড় ডেটা বা ফাইল প্রসেসিংয়ের জন্য উপযুক্ত, কারণ এগুলি একসাথে অনেক ডেটা প্রসেস করতে সক্ষম এবং র্যাম-এ বড় ডেটা লোড করার প্রয়োজন পড়ে না।
  • Readable এবং Writable Streams একসাথে ব্যবহার করে আপনি ডেটা এক স্ট্রিম থেকে অন্য স্ট্রিমে পাঠাতে পারেন, যা স্ট্রিম পাইপলাইন তৈরির জন্য ব্যবহৃত হয়।
Content added By

Pipes এবং Data Streaming

197

Pipes এবং Data Streaming হল Node.js এ ডাটা ট্রান্সফার ও প্রসেসিং এর জন্য ব্যবহৃত দুটি শক্তিশালী প্রযুক্তি। Pipes ব্যবহার করে আপনি এক ধরনের স্ট্রিম থেকে অন্য ধরনের স্ট্রিমে ডাটা পাঠাতে পারেন, এবং Data Streaming হল ডাটা প্রক্রিয়াকরণের জন্য একটি সিস্টেম যা ছোট ছোট চাঙ্কে ডাটা পাঠানো এবং গ্রহণ করার অনুমতি দেয়।

Node.js এ Streams ডাটা ট্রান্সফার বা প্রসেসিং এর জন্য ব্যবহৃত হয়, এবং Pipes স্ট্রিমের মধ্যে ডাটা পাস করতে ব্যবহৃত হয়।


১. Data Streaming

Data Streaming হল একটি প্রক্রিয়া যেখানে ডাটা স্নাত (streamed) হয়ে একটানা পাঠানো বা গ্রহণ করা হয়, সাধারণত বড় ডাটা সেটের ক্ষেত্রে। Data Streaming দুটি ধাপে কাজ করে:

  1. Readable Stream: যেখানে ডাটা পড়া হয় (যেমন ফাইল থেকে ডাটা পড়া, HTTP রিকোয়েস্ট থেকে ডাটা পাওয়া)
  2. Writable Stream: যেখানে ডাটা লেখা হয় (যেমন ফাইলে ডাটা লেখা, HTTP রেসপন্স পাঠানো)

Streaming হল non-blocking এবং asynchronous প্রক্রিয়া, যা বৃহৎ ডাটা সাইজগুলো সহজে ম্যানেজ করতে সহায়তা করে এবং কম মেমরি ব্যবহার করে।

Node.js এ Data Streaming উদাহরণ:

  1. Readable Stream Example:
    এখানে, আমরা একটি ফাইল থেকে ডাটা পড়ছি:
const fs = require('fs');

// ফাইল থেকে ডাটা পড়া
const readableStream = fs.createReadStream('example.txt', 'utf8');

// ডাটা পড়া হচ্ছে
readableStream.on('data', (chunk) => {
  console.log(`Reading chunk: ${chunk}`);
});

// 'end' ইভেন্টে যখন ফাইল পড়া সম্পন্ন হয়
readableStream.on('end', () => {
  console.log('File reading complete');
});
  1. Writable Stream Example:
    এখানে, আমরা একটি ফাইলে ডাটা লিখছি:
const fs = require('fs');

// ফাইলে ডাটা লেখা
const writableStream = fs.createWriteStream('output.txt');

// ডাটা লেখা হচ্ছে
writableStream.write('Hello, world!\n');
writableStream.write('This is a new line.\n');

// 'finish' ইভেন্টে যখন ডাটা লেখার কাজ সম্পন্ন হয়
writableStream.on('finish', () => {
  console.log('Data written to file');
});

২. Pipes

Pipes হল একটি প্রযুক্তি যা Readable Stream থেকে ডাটা নিয়ে তা Writable Stream এ পাঠাতে ব্যবহৃত হয়। Node.js এ pipe() মেথড ব্যবহার করে আপনি একটি স্ট্রিম থেকে আরেকটি স্ট্রিমে ডাটা সহজে পাস করতে পারেন।

এটি ডাটা ট্রান্সফারের জন্য একটি সরল ও কার্যকরী উপায়, যা ব্যাকপ্রেসার (backpressure) ব্যবস্থাপনা করে এবং স্ট্রিমগুলির মধ্যে ডাটা পাঠানোর প্রক্রিয়া খুবই দ্রুত ও দক্ষ করে তোলে।

pipe() মেথড ব্যবহার করা:

ফাইল কপি করার উদাহরণ:
এখানে, আমরা একটি ফাইলের ডাটা এক ফাইল থেকে অন্য ফাইলে কপি করছি:

const fs = require('fs');

// Readable Stream - ফাইল থেকে ডাটা পড়া
const readableStream = fs.createReadStream('source.txt');

// Writable Stream - ফাইলে ডাটা লেখা
const writableStream = fs.createWriteStream('destination.txt');

// Pipe মেথড ব্যবহার করে ডাটা এক ফাইল থেকে অন্য ফাইলে পাঠানো
readableStream.pipe(writableStream);

// 'finish' ইভেন্টে যখন সব ডাটা লেখা হয়ে যায়
writableStream.on('finish', () => {
  console.log('File copied successfully!');
});

এখানে, readableStream থেকে ডাটা writableStream এ পাস করা হয়েছে pipe() মেথডের মাধ্যমে। এটি দ্রুত ও দক্ষভাবে ডাটা ট্রান্সফার করতে সহায়তা করে।


৩. Pipes এবং Backpressure

একটি গুরুত্বপূর্ণ ধারণা যখন স্ট্রিম এবং পিপস নিয়ে কাজ করা হয় তা হল backpressureBackpressure হলো সেই পরিস্থিতি যখন ডাটা প্রযোজনার হার (writing rate) বেশি, এবং ডাটা প্রাপ্তির হার (reading rate) কম, ফলে স্ট্রিমের মধ্যে চাপ সৃষ্টি হয়।

Node.js এর স্ট্রিমিং সিস্টেম স্বয়ংক্রিয়ভাবে backpressure হ্যান্ডেল করে, যাতে অপ্রয়োজনীয় ডাটা হারিয়ে না যায় এবং সিস্টেমে সমস্যা না হয়। যখন ডাটা পাঠানোর গতি বেশি হয় এবং পাইপটি পুরোপুরি পূর্ণ হয়ে যায়, তখন এটি পিপিং বন্ধ করে দেয় এবং পরবর্তী স্ট্রিমে কাজ শুরু হতে দেয়।


৪. Streams এবং Pipes ব্যবহার করে বড় ফাইল প্রসেসিং

Node.js এর Streams এবং Pipes বড় ফাইলগুলিকে প্রক্রিয়া করার জন্য উপযুক্ত। যখন একটি বড় ফাইল পুরোপুরি মেমরিতে লোড করা হয়, তখন এটি মেমরি ব্যবহারকে অত্যধিক বাড়িয়ে ফেলে। স্ট্রিমিং মাধ্যমে ছোট ছোট চাঙ্কে ডাটা প্রসেস করা হয় এবং এটি অনেক কম মেমরি ব্যবহার করে।

উদাহরণ: বড় ফাইল থেকে ডাটা প্রসেস করা

const fs = require('fs');

// Readable Stream থেকে বড় ফাইল পড়া এবং Writable Stream এ পাঠানো
const readableStream = fs.createReadStream('largefile.txt', 'utf8');
const writableStream = fs.createWriteStream('processedfile.txt');

// Pipe মেথড ব্যবহার করে ডাটা পাঠানো
readableStream.pipe(writableStream);

এখানে, বড় ফাইলটি একটি ছোট অংশে বিভক্ত হয়ে একে একে পাঠানো হচ্ছে, যা মেমরি ব্যবহারের জন্য উপযোগী।


সারাংশ

  • Data Streaming হল একটি প্রক্রিয়া যেখানে ডাটা স্নাতভাবে পাঠানো বা গ্রহণ করা হয়, সাধারণত বৃহৎ ডাটা সাইজগুলির জন্য। Node.js এ, Readable এবং Writable স্ট্রিম ব্যবহার করে ডাটা পড়া ও লেখা হয়।
  • Pipes হল একটি প্রযুক্তি যা pipe() মেথডের মাধ্যমে Readable Stream থেকে Writable Stream এ ডাটা পাঠানোর কাজ করে। এটি স্ট্রিমগুলির মধ্যে দ্রুত এবং কার্যকরীভাবে ডাটা পাঠাতে সাহায্য করে।
  • Backpressure হ্যান্ডলিং স্ট্রিম সিস্টেমের একটি গুরুত্বপূর্ণ অংশ, যা ডাটা পাঠানোর এবং গ্রহণের মধ্যে সঠিক সমন্বয় নিশ্চিত করে, যাতে স্ট্রিমে কোনো চাপ সৃষ্টি না হয়।
Content added By

Buffers এর মাধ্যমে Binary Data Handling

170

Node.js এ Buffers হল এমন একটি ডাটা স্ট্রাকচার যা বাইনারি ডাটা (যেমন ফাইল বা নেটওয়ার্ক থেকে প্রাপ্ত ডাটা) প্রসেস করতে ব্যবহৃত হয়। JavaScript সাধারণত স্ট্রিং এবং অবজেক্ট সহ কাজ করে, কিন্তু বাইনারি ডাটা পরিচালনা করতে Buffers ব্যবহার করা হয়। Buffers এক ধরনের অ্যাসিনক্রোনাস ডাটা হ্যান্ডলিং ফিচার, যা Node.js এর ফাইল সিস্টেম বা নেটওয়ার্ক অপারেশনগুলিতে ব্যবহৃত হয়, যেখানে বাইনারি ডাটা প্রক্রিয়াকরণের প্রয়োজন হয়।

বাফার সাধারণত বাইনারি ডাটা ম্যানিপুলেশন, যেমন ফাইল পড়া, ইমেজ বা ভিডিও ফাইল থেকে ডাটা এক্সট্র্যাক্ট করা, নেটওয়ার্কিং, বা ডেটাবেস ইন্টারঅ্যাকশন ইত্যাদির জন্য ব্যবহৃত হয়।

১. Buffer তৈরি করা

Node.js এ Buffer একটি বিশেষ ধরনের অবজেক্ট যা বাইনারি ডাটা ধারণ করে। এটি Buffer.alloc(), Buffer.from(), অথবা new Buffer() এর মাধ্যমে তৈরি করা যেতে পারে (যদিও new Buffer() এখন পুরানো এবং deprecated, তাই Buffer.alloc() বা Buffer.from() ব্যবহার করা উত্তম)।

Buffer.alloc() ব্যবহার করা

Buffer.alloc() একটি নির্দিষ্ট সাইজের একটি নতুন বাফার তৈরি করে এবং সমস্ত বাইট শূন্য দিয়ে পূর্ণ করে।

const buffer = Buffer.alloc(10);  // 10 বাইটের একটি বাফার তৈরি করা হচ্ছে
console.log(buffer);  // <Buffer 00 00 00 00 00 00 00 00 00 00>

Buffer.from() ব্যবহার করা

Buffer.from() একটি স্ট্রিং, অ্যারে বা অন্য একটি বাফার থেকে নতুন বাফার তৈরি করতে ব্যবহৃত হয়।

const buffer = Buffer.from('Hello, world!', 'utf-8');  // UTF-8 এনকোডিং দিয়ে স্ট্রিং থেকে বাফার তৈরি
console.log(buffer);  // <Buffer 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21>

এখানে, Buffer.from() ফাংশনটি স্ট্রিং 'Hello, world!' কে বাফারে রূপান্তরিত করেছে।


২. Buffer থেকে ডাটা পড়া

Buffer একটি বাইনারি ডাটা ধারণ করে, এবং আপনি বিভিন্ন পদ্ধতিতে তার মধ্যে থাকা ডাটা অ্যাক্সেস করতে পারেন।

Buffer থেকে স্ট্রিং পড়া

Buffer থেকে স্ট্রিং রিটার্ন করতে toString() মেথড ব্যবহার করা হয়:

const buffer = Buffer.from('Hello, world!', 'utf-8');
console.log(buffer.toString('utf-8'));  // "Hello, world!"

Buffer থেকে নম্বর পড়া

Buffer এ একটি নির্দিষ্ট পজিশন থেকে ৮-বিট, ১৬-বিট বা ৩২-বিট সংখ্যার মান পড়তে readUInt8(), readUInt16LE(), বা readUInt32LE() মেথড ব্যবহার করা হয়।

const buffer = Buffer.alloc(4);
buffer.writeUInt8(255, 0);  // 255 কে 0 পজিশনে লিখে
buffer.writeUInt8(128, 1);  // 128 কে 1 পজিশনে লিখে
console.log(buffer);  // <Buffer ff 80 00 00>

এখানে, writeUInt8() দিয়ে একটি ৮-বিট unsigned ইন্টিজার লিখা হয়েছে এবং Buffer এর নির্দিষ্ট পজিশনে সংখ্যাটি জমা করা হয়েছে।


৩. Buffer ম্যানিপুলেশন

Buffer এর ডাটা পরিবর্তন করতে আপনি সরাসরি তাকে modify করতে পারেন। যেমন, কোনও নির্দিষ্ট পজিশনে ডাটা লিখে দেওয়া, নতুন ডাটা অ্যাড করা ইত্যাদি।

ডাটা লেখা

write() মেথড দিয়ে একটি নির্দিষ্ট পজিশনে ডাটা লেখা যায়।

const buffer = Buffer.alloc(10);
buffer.write('Hello');
console.log(buffer);  // <Buffer 48 65 6c 6c 6f 00 00 00 00 00>

এখানে, "Hello" স্ট্রিংটি বাফারের প্রথম পাঁচটি বাইটে লেখা হয়েছে। বাকি বাইটগুলি শূন্য থাকবে।

Buffer একে অপরের সাথে যুক্ত করা

Buffer.concat() মেথড ব্যবহার করে একাধিক বাফারকে যুক্ত করা যায়।

const buffer1 = Buffer.from('Hello, ');
const buffer2 = Buffer.from('world!');
const combined = Buffer.concat([buffer1, buffer2]);
console.log(combined.toString());  // "Hello, world!"

এখানে, দুটি বাফার একত্রিত করে একটি নতুন বাফার তৈরি করা হয়েছে।


৪. Buffer ব্যবহার করে ফাইলের বাইনারি ডাটা পড়া

Node.js এ fs মডিউল ব্যবহার করে আপনি বাইনারি ফাইলের ডাটা Buffer হিসেবে পড়তে পারেন। এটি সাধারণত ইমেজ, ভিডিও বা অন্যান্য বাইনারি ডাটা ফাইলের সাথে কাজ করতে ব্যবহৃত হয়।

ফাইল থেকে বাইনারি ডাটা পড়া

const fs = require('fs');

// ফাইল থেকে বাইনারি ডাটা পড়া
fs.readFile('image.png', (err, data) => {
    if (err) {
        console.log('Error:', err);
    } else {
        console.log('File data (Buffer):', data);
    }
});

এখানে, fs.readFile() মেথডটি একটি ফাইল থেকে বাইনারি ডাটা পড়ে এবং তা Buffer হিসেবে রিটার্ন করে। আপনি পরে এই ডাটা প্রসেস করতে পারবেন।


৫. Buffers এর মাধ্যমে ডাটা ট্রান্সফার এবং নেটওয়ার্কিং

Buffers বিভিন্ন নেটওয়ার্ক অপারেশনে ব্যবহৃত হয়, যেমন TCP/UDP সোকেটের মাধ্যমে বাইনারি ডাটা ট্রান্সফার করা। এটি দ্রুত ডাটা স্থানান্তর করার জন্য কার্যকরী, কারণ বাইনারি ডাটা সরাসরি মেমোরিতে রাখা যায়।

const net = require('net');

const client = net.createConnection({ port: 8080 }, () => {
    console.log('Connected to server!');
    client.write(Buffer.from('Hello server!'));
});

client.on('data', (data) => {
    console.log('Received from server:', data.toString());
    client.end();
});

এখানে, আমরা Buffer.from() ব্যবহার করে একটি স্ট্রিংকে বাইনারি ডাটায় রূপান্তর করেছি এবং একটি TCP সোকেটের মাধ্যমে সার্ভারে পাঠাচ্ছি।


সারাংশ

  • Buffers Node.js এ বাইনারি ডাটা হ্যান্ডলিং এর জন্য একটি গুরুত্বপূর্ণ ডাটা স্ট্রাকচার। এটি অ্যাসিনক্রোনাস এবং নেটওয়ার্কিং অপারেশনে ব্যবহৃত হয়।
  • Buffer.alloc() এবং Buffer.from() ব্যবহার করে আপনি একটি বাফার তৈরি করতে পারেন, এবং toString(), write(), এবং readUInt8() এর মাধ্যমে বাফারে ডাটা ম্যানিপুলেট করতে পারেন।
  • আপনি Buffers ব্যবহার করে ফাইল, নেটওয়ার্কিং এবং বাইনারি ডাটা প্রসেসিং কার্যক্রম আরও কার্যকরী ও দ্রুত করতে পারেন।

Buffers Node.js এর গুরুত্বপূর্ণ অংশ, যা আপনাকে বাইনারি ডাটার উপর আরও নিয়ন্ত্রণ প্রদান করে এবং এর মাধ্যমে আপনি সহজে ইমেজ, ভিডিও, বা অন্যান্য বাইনারি ডাটা ফাইলের সাথে কাজ করতে পারেন।

Content added By
Promotion
NEW SATT AI এখন আপনাকে সাহায্য করতে পারে।

Are you sure to start over?

Loading...